﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;

public class InkjetPrinterController : IDisposable
{
    #region 常量定义
    // 协议常量
    private const byte STX = 0x1B; // 起始符
    private const byte S_HEADER = 0x53; // 'S' 命令头
    private const byte D_HEADER = 0x44; // 'D' 数据头
    private const byte CR = 0x0D; // 回车
    private const byte LF = 0x0A; // 换行

    // 响应码
    private const string OK0 = "OK0"; // 串口打开
    private const string OK1 = "OK1"; // 准备好接收
    private const string OK2 = "OK2"; // 设置成功
    private const string OK3 = "OK3"; // 清除缓存成功
    private const string OK4 = "OK4"; // 串口关闭
    private const string OK5 = "OK5"; // 打印完成
    private const string E01 = "E01"; // 校验错误
    private const string E02 = "E02"; // 缓存满

    // 命令标识
    private const string CMD_PRINT_TRIGGER = "00"; // 触发打印
    private const string CMD_PRINT_DIRECT = "01"; // 直接打印
    private const string CMD_READY_QUERY = "AK"; // 查询就绪
    private const string CMD_CLEAR_BUFFER = "77"; // 清除缓存
    private const string CMD_CANCEL_PRINT = "#c"; // 取消打印
    private const string CMD_CONTINUE_PRINT = "#d"; // 继续打印
    #endregion

    #region 事件定义
    // 自定义事件参数类
    public class PrintCompletedEventArgs : EventArgs
    {
        public string Message { get; } // 封装字符串数据
        public PrintCompletedEventArgs(string message) => Message = message;
    }

    // 修改事件声明
    public event EventHandler<PrintCompletedEventArgs> PrintCompleted;
    //public event EventHandler<string> PrintCompleted; // 打印完成事件
    // 数据接收事件参数
    public class DataReceivedEventArgs : EventArgs
    {
        public string Message { get; }  // 封装字符串数据
        public DataReceivedEventArgs(string message) => Message = message;
    }

    // 错误事件参数
    public class ErrorOccurredEventArgs : EventArgs
    {
        public string ErrorMessage { get; }  // 封装错误信息
        public ErrorOccurredEventArgs(string errorMessage) => ErrorMessage = errorMessage;
    }
    // 修改后的事件声明
    public event EventHandler<DataReceivedEventArgs> DataReceived;   // 数据接收事件
    public event EventHandler<ErrorOccurredEventArgs> ErrorOccurred;  // 错误发生事件
    #endregion

    #region 字段
    private SerialPort _serialPort;
    private readonly object _lockObject = new object();
    private readonly List<byte> _receiveBuffer = new List<byte>();
    private bool _isDisposed = false;
    #endregion

    #region 属性
    public string PortName { get; private set; }
    public int BaudRate { get; private set; } = 115200;
    public bool IsConnected => _serialPort?.IsOpen ?? false;
    public string LastError { get; private set; }
    #endregion

    #region 构造函数
    public InkjetPrinterController()
    {
        InitializeSerialPort();
    }
    #endregion

    #region 初始化
    private void InitializeSerialPort()
    {
      

      
    }
    #endregion

    #region 连接管理
    public bool Connect(string portName, int baudRate = 115200)
    {

        PortName = portName;
        BaudRate = baudRate;
     
        try
        {
            if (_serialPort==null|| !_serialPort.IsOpen)
            {
                _serialPort = new SerialPort(PortName, BaudRate, Parity.None, 8, StopBits.One)
                {
                    Handshake = Handshake.None,
                    ReadTimeout = 1000,
                    WriteTimeout = 1000,
                    Encoding = Encoding.Default// 使用单字节编码
                };
                _serialPort.DataReceived += SerialPort_DataReceived;
                _serialPort.ErrorReceived += SerialPort_ErrorReceived;
                _serialPort.Open();
                _isDisposed = false;
                // _serialPort.Close();
            }

            
            LastError = string.Empty;
            return true;
        }
        catch (Exception ex)
        {
            LastError = $"连接失败: {ex.Message}";
            OnErrorOccurred(LastError);
            return false;
        }
    }

    public void Disconnect()
    {
        try
        {
            if (_serialPort.IsOpen)
            {
                _serialPort.Close();
            }
        }
        catch (Exception ex)
        {
            LastError = $"断开连接失败: {ex.Message}";
            OnErrorOccurred(LastError);
        }
    }
    #endregion

    #region 基本操作命令
    public bool OpenPrinter()
    {
        // 发送启动打印命令
        return SendCommand(CMD_PRINT_DIRECT, new byte[0]);
    }

    public bool ClosePrinter()
    {
        // 发送停止打印命令（实际协议可能需要特定命令）
        return SendCommand(CMD_CANCEL_PRINT, new byte[0]);
    }

    public bool ClearBuffer()
    {
        return SendCommand(CMD_CLEAR_BUFFER, new byte[0]);
    }

    public bool CheckReady()
    {
        return SendCommand(CMD_READY_QUERY, new byte[0]);
    }
    #endregion

    #region 发送数据
    public bool SendPrintData(string content, bool directPrint = false)
    {
        try
        {
            // 将内容转换为UTF8字节
            byte[] contentBytes = Encoding.UTF8.GetBytes(content);

            // 选择命令类型
            string commandType = directPrint ? CMD_PRINT_DIRECT : CMD_PRINT_TRIGGER;

            // 发送数据
            return SendCommand(commandType, contentBytes);
        }
        catch (Exception ex)
        {
            LastError = $"发送数据失败: {ex.Message}";
            OnErrorOccurred(LastError);
            return false;
        }
    }

    //清空缓存
    public bool ClearData()
    {
        try
        {
            // 将内容转换为UTF8字节
            byte[] contentBytes = Encoding.UTF8.GetBytes("");

            // 选择命令类型
            string commandType ="77";

            // 发送数据
            return SendCommand(commandType, contentBytes);
        }
        catch (Exception ex)
        {
            LastError = $"发送数据失败: {ex.Message}";
            OnErrorOccurred(LastError);
            return false;
        }
    }

    public bool SetPrintCount(int count)
    {
        try
        {
            byte[] countBytes = new byte[3];
            countBytes[0] = (byte)(count & 0xFF);         // 低字节
            countBytes[1] = (byte)((count >> 8) & 0xFF);  // 中字节
            countBytes[2] = (byte)((count >> 16) & 0xFF); // 高字节

            // 构建设置次数命令帧
            byte[] frame = BuildCommandFrame("FF", countBytes);
            return SendRawData(frame);
        }
        catch (Exception ex)
        {
            LastError = $"设置打印次数失败: {ex.Message}";
            OnErrorOccurred(LastError);
            return false;
        }
    }
    #endregion

    #region 核心通信方法
    private bool SendCommand(string command, byte[] data)
    {
        byte[] frame = BuildCommandFrame(command, data);
        return SendRawData(frame);
    }

    private byte[] BuildCommandFrame(string command, byte[] data)
    {
        // 计算总长度: STX + S_HEADER + command(2) + data + checksum + CR + LF
        int totalLength = 2 + 2 + data.Length + 1 + 2;
        byte[] frame = new byte[totalLength];
        int index = 0;

        // 起始位
        frame[index++] = STX;
        frame[index++] = S_HEADER;

        // 命令标识（2字节）
        byte[] cmdBytes = Encoding.ASCII.GetBytes(command);
        frame[index++] = cmdBytes[0];
        frame[index++] = cmdBytes[1];

        // 数据内容
        foreach (byte b in data)
        {
            frame[index++] = b;
        }

        // 计算校验和（从STX到最后一个数据字节）
        byte checksum = CalculateChecksum(frame, 0, index - 1);
        frame[index++] = checksum;

        // 回车换行符
        frame[index++] = CR;
        frame[index++] = LF;

        return frame;
    }

    private bool SendRawData(byte[] data)
    {
        lock (_lockObject)
        {
            try
            {
                if (!_serialPort.IsOpen)
                {
                    LastError = "串口未连接";
                    return false;
                }
                lock (o)
                {
                    isOk = false;
                }
                _serialPort.Write(data, 0, data.Length);

                return true;
                // 等待响应
                //return WaitForResponse(500);
              
            }
            catch (Exception ex)
            {
                LastError = $"发送数据失败: {ex.Message}";
                OnErrorOccurred(LastError);
                return false;
            }
        }
    }

    bool isOk = false;
    object o=new object();

    private bool WaitForResponse(int timeoutMs)
    {
        DateTime endTime = DateTime.Now.AddMilliseconds(timeoutMs);
        bool responseReceived = false;
        bool isSuccess = false;

        while (DateTime.Now < endTime && !responseReceived)
        {
            Thread.Sleep(10);
            if (isOk)
            {
                isSuccess = true;
                break;
            }
        }

        return isSuccess;
    }
    #endregion

    #region 数据接收处理
    private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        try
        {
            lock (_lockObject)
            {
                int bytesToRead = _serialPort.BytesToRead;
            if (bytesToRead > 0)
            {
                byte[] buffer = new byte[bytesToRead];
                _serialPort.Read(buffer, 0, bytesToRead);

                
                    _receiveBuffer.AddRange(buffer);
               

                ProcessReceivedData();
            }
            }
        }
        catch (Exception ex)
        {
            LastError = $"数据接收错误: {ex.Message}";
            OnErrorOccurred(LastError);
        }
    }

    private void ProcessReceivedData()
    {
        lock (_lockObject)
        {
            var frames = ExtractCompleteFrames();
            foreach (var frame in frames)
            {
               // OnDataReceived(frame);
                // 处理特定响应
                if (frame.StartsWith("OK"))
                {
                    HandleOkResponse(frame);
                }
                else if (frame.StartsWith("E"))
                {
                    HandleErrorResponse(frame);
                }
            }
        }
    }

    private List<string> ExtractCompleteFrames()
    {
        var completeFrames = new List<string>();
        int startIndex = -1;

        for (int i = 0; i < _receiveBuffer.Count - 1; i++)
        {
            // 查找帧起始符 STX
            if (_receiveBuffer[i] == STX && i + 1 < _receiveBuffer.Count)
            {
                startIndex = i;
            }

            // 查找帧结束符 CR LF
            if (startIndex != -1 && i + 1 < _receiveBuffer.Count )
            {
                // 提取完整帧
                int frameLength = _receiveBuffer.Count;
                byte[] frameBytes = _receiveBuffer.GetRange(startIndex, frameLength).ToArray();

                // 转换为字符串（跳过STX和头部）
                string frameText = Encoding.ASCII.GetString(frameBytes, 1, frameLength-1);

                completeFrames.Add(frameText);

                // 移除已处理的帧
                _receiveBuffer.RemoveRange(startIndex, frameLength);
                i = startIndex - 1; // 重置索引
                startIndex = -1;
            }
        }

        return completeFrames;
    }

    private void HandleOkResponse(string response)
    {
        switch (response)
        {
            case OK2:
                lock (o) { 
                isOk = true;
                }
                break;
            case OK5:
                OnPrintCompleted("打印完成");
                break;
            case OK0:
                OnDataReceived("串口已打开");
                break;
            case OK4:
                OnDataReceived("串口已关闭");
                break;
            default:
                OnDataReceived($"操作成功: {response}");
                break;
        }
    }

    private void HandleErrorResponse(string response)
    {
        string errorMessage;
        switch (response)
        {
            case "E01":
                errorMessage = "校验和错误";
                break;
            case "E02":
                errorMessage = "缓存已满";
                break;
            default:
                errorMessage = $"未知错误: {response}";
                break;
        }

        LastError = errorMessage;
        OnErrorOccurred(errorMessage);
    }
    #endregion

    #region 工具方法
    private byte CalculateChecksum(byte[] data, int start, int end)
    {
        byte checksum = 0;
        for (int i = start; i <= end; i++)
        {
            checksum += data[i];
        }
        return checksum;
    }

    private void SerialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
    {
        LastError = $"串口错误: {e.EventType}";
        OnErrorOccurred(LastError);
    }
    #endregion

    #region 事件触发
    protected virtual void OnPrintCompleted(string message)
    {
        PrintCompleted?.Invoke(this, new PrintCompletedEventArgs(message));
    }

    protected virtual void OnDataReceived(string data)
    {
        DataReceived?.Invoke(this, new DataReceivedEventArgs(data));
    }

    protected virtual void OnErrorOccurred(string error)
    {
        ErrorOccurred?.Invoke(this, new ErrorOccurredEventArgs(error));
    }
    #endregion

    #region IDisposable 实现
    public void Dispose()
    {
        if (!_isDisposed)
        {
            _isDisposed = true;

            if (_serialPort != null)
            {
                _serialPort.DataReceived -= SerialPort_DataReceived;
                _serialPort.ErrorReceived -= SerialPort_ErrorReceived;

                if (_serialPort.IsOpen)
                {
                    _serialPort.Close();
                }

                _serialPort.Dispose();
            }
        }
    }
    #endregion
}